package com.gylang.crypto.adapter;

import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gylang.crypto.annotation.CryptoRequest;
import com.gylang.crypto.annotation.CryptoResponse;
import com.gylang.crypto.crypto.CryptoContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;

/**
 * 主要测试 和 思路
 *
 * @author gylang
 * data 2020/10/28
 * @version v0.0.1
 * @deprecated 这个方法实现统一的执行调用也行 当时得自己实现所有得参数赋值
 * 如果实现一自定义得分发处理器 这个方式更加合适, 更加偏向底层调用, 减少变量查询处理器
 */
@Slf4j
//@Component
@Deprecated
public class CryptHandlerAdapter implements HandlerAdapter {
    @Autowired
    private CryptoContext cryptoContext;
    private static final String KEY = "O4kD+LiM7tNfIwL+ky9a+w==";

    @Override
    public boolean supports(Object handler) {
        HandlerMethod method = (HandlerMethod) handler;
        log.info("会进来吗");
        return method.hasMethodAnnotation(CryptoResponse.class);
    }

    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            log.info("method.hasMethodAnnotation(CryptResponse.class) {}", method.hasMethodAnnotation(CryptoResponse.class));
            log.info("method.hasMethodAnnotation(CryptRequest.class) {}", method.hasMethodAnnotation(CryptoRequest.class));
            MethodParameter methodParameter = method.getMethodParameters()[0];
            CryptoRequest cryptoRequest = methodParameter.getParameterAnnotation(CryptoRequest.class);
            if (null != cryptoRequest) {
                // 获取入参
                String requestBody = IoUtil.read(request.getInputStream(), StandardCharsets.UTF_8);
                JSONObject map = JSON.parseObject(requestBody);
                String content = map.getString("content");
                String decrypt = cryptoContext.decrypt(cryptoRequest.type(), KEY, content);
                // 解密
                Object param = JSON.parseObject(decrypt, methodParameter.getParameterType());
                // 调用业务方法
                Object res = method.getMethod().invoke(method.getBean(), param);
                // 加密结果
                MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
                ModelAndView modelAndView = new ModelAndView(jsonView);
                modelAndView.addObject("content", cryptoContext.encrypt(cryptoRequest.type(), KEY, JSON.toJSONString(res)));
                return modelAndView;
            }
        }
        response.getWriter().write("You think i can't find the invkoke methed, but I can get the controller he called. but, how can I invkoke the method ");
        return null;
    }

    @Override
    public long getLastModified(HttpServletRequest request, Object handler) {
        return 0;
    }


}
